﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace GbopSdk
{
	public static class JsonHelper
	{
		public static JToken ReadJSON(string jsonStr)
		{
			JObject jobj = JObject.Parse(jsonStr);
			JToken result = jobj as JToken;
			return result;
		}
		/// <summary>
		/// 遍历所以节点，替换其中某个节点的值
		/// </summary>
		/// <param name="jobj">json数据</param>
		/// <param name="nodeName">节点名</param>
		/// <param name="value">新值</param>
		public static void JSON_SetChildNodes(this JToken jobj, string nodeName, string value)
		{
			try
			{
				JToken result = jobj as JToken;//转换为JToken
				JToken result2 = result.DeepClone();//复制一个返回值，由于遍历的时候JToken的修改回终止遍历，因此需要复制一个新的返回json
													//遍历
				var reader = result.CreateReader();
				while (reader.Read())
				{
					if (reader.Value != null)
					{
						if (reader.TokenType == JsonToken.String || reader.TokenType == JsonToken.Integer || reader.TokenType == JsonToken.Float)
						{
							Regex reg = new Regex(@"" + nodeName + "$");
							//SelectToken(Path)方法可查找某路径下的节点，在Newtonsoft.Json 4.5 版本中不可使用正则匹配，在6.0版本中可用使用，会方便很多，6.0版本下替换值会更方便，这个需要特别注意的
							if (reg.IsMatch(reader.Path))
							{
								result2.SelectToken(reader.Path).Replace(value);
							}
						}
					}
				}
				jobj = result2;
			}
			catch (Exception ex)
			{
			}
		}
		/// <summary>
		/// 获取相应子节点的值
		/// </summary>
		/// <param name="childnodelist"></param>
		public static string JSON_SeleteNode(this JToken json, string ReName)
		{
			try
			{
				string result = "";
				//这里6.0版块可以用正则匹配
				var node = json.SelectToken("$.." + ReName);
				if (node != null)
				{
					//判断节点类型
					if (node.Type == JTokenType.String || node.Type == JTokenType.Integer || node.Type == JTokenType.Float)
					{
						//返回string值
						result = node.Value<object>().ToString();
					}
				}
				return result;
			}
			catch (Exception ex)
			{
				return "";
			}
		}

		public static string CovertDefineToObject(JToken jToken)
		{
			if (jToken["type"] is JValue jValue)
			{
				if (jValue.Value.Equals("object"))
				{
					if (jToken["properties"] == null)
					{
						return $"{ "{ }" }";
					}
					else
					{
						return $"{ "{" + Environment.NewLine + CovertDefineToObject(jToken["properties"]) + Environment.NewLine + "}" }";
					}
				}
				else if (jValue.Value.Equals("array"))
				{
					if (jToken["properties"] == null)
					{
						return $"{ "" }";
					}
					else
					{
						return $"{ Environment.NewLine + CovertDefineToObject(jToken["properties"]) + Environment.NewLine }";
					}
				}
				else if (jValue.Value.Equals("string") || jValue.Value.Equals("integer") || jValue.Value.Equals("number") || jValue.Value.Equals("boolean"))
				{
					return "\"\"";
				}
				else
				{
					throw new Exception(jToken + string.Empty);
				}
			}
			else
			{
				string s = "";
				foreach (JToken item in jToken.Children())
				{
					var pc = ((JProperty)item).Children();
					if (pc.Count() == 1)
					{
						JToken jTokenChildren = pc.ElementAt(0);
						if (jTokenChildren.Type == JTokenType.Array)
						{
							s += "{\"" + ((JProperty)item).Name + "\": []},";
						}
						else if (jTokenChildren.Type == JTokenType.String)
						{
							s += item.ToString() + ",";
						}
						else if (jTokenChildren.Path == "$ref")
						{

						}
						else if (jTokenChildren["type"] == null)
						{
							if (jTokenChildren.Path == "definitions")
								s += CovertDefineToObject(jTokenChildren.Children().ElementAt(0).Children().ElementAt(0));
							else
								throw new Exception(jTokenChildren + string.Empty);
						}
						else
						{
							var jtype = ((JValue)(jTokenChildren["type"]));
							if (jtype.Value.Equals("object"))
							{
								s += "\"" + ((JProperty)item).Name + "\": " + CovertDefineToObject(jTokenChildren) + " ,";
							}
							else if (jtype.Value.Equals("array"))
							{
								s += "\"" + ((JProperty)item).Name + "\": [ " + CovertDefineToObject(jTokenChildren["items"]) + " ],";
							}
							else if (jtype.Value.Equals("string") || jtype.Value.Equals("integer") || jtype.Value.Equals("number") || jtype.Value.Equals("boolean"))
							{
								s += "\"" + ((JProperty)item).Name + "\": \"" + (jTokenChildren["description"] + string.Empty).Replace("\\", "\\\\").Replace("\"", "\\\"") + "\",";
							}
							else
							{
								throw new Exception(jTokenChildren + string.Empty);
							}
						}
					}
					else
					{
						throw new Exception(item + string.Empty);
					}
				}
				return s.TrimEnd(',');
			}
		}

		public static string FormatJsonString(string str)
		{
			try
			{
				//if (str.Length >= 20000)
				//{
				//	return Environment.NewLine + str + Environment.NewLine + "***【以下内容被GBOP主动截断，无法显示】***";
				//}
				if (!str.StartsWith("{"))
				{
					str = "{" + str;
				}
				if (!str.EndsWith("}"))
				{
					str = str + "}";
				}
				//格式化json字符串
				JsonSerializer serializer = new JsonSerializer();
				TextReader tr = new StringReader(str);
				JsonTextReader jtr = new JsonTextReader(tr);
				object obj = serializer.Deserialize(jtr);
				if (obj != null)
				{
					StringWriter textWriter = new StringWriter();
					JsonTextWriter jsonWriter = new JsonTextWriter(textWriter)
					{
						Formatting = Formatting.Indented,
						Indentation = 4,
						IndentChar = ' '
					};
					serializer.Serialize(jsonWriter, obj);
					return textWriter.ToString();
				}

				return str;
			}
			catch (Exception ex)
			{
				return "{" + ex + Environment.NewLine + str + "}";
			}
		}
	}
}
